--[[
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

Detection for CVE-2015-2377 expects XLSX

This lua script can be run standalone and verbosely on a Flash file with
echo "run()" | luajit -i <script name> <xlsx file>

Will Metcalf
Chris Wakelin
Francis Trudeau
--]]

require("zip")

function init (args)
    local needs = {}
    needs["http.response_body"] = tostring(true)
    return needs
end



function find_legend_count(u,filename,verbose)
    local rtn = 0

    legendelements = string.gfind(u, "<c:legend.-</c:legend[^E]")
    for s in legendelements do
        if string.match(s, "<c:legendPos") then
            if (verbose==1) then print ("Valid legend") end
        else
            if (verbose==1) then print ("Possible CVE-2015-2377 found") end
            rtn = 1
        end
    end
end

function xls_handler(t,verbose)
    rtn = 0
    tmpname = os.tmpname()
    
    tmp = io.open(tmpname,'w')
    tmp:write(t)
    tmp:close()

    z,err = zip.open(tmpname)
    local buffers = {}
    if z then
        for w in z:files() do
            if string.find(w.filename,"xl/charts/",1,true) then
                f = z:open(w.filename);
                u = f:read("*all")
                f:close()
                if (verbose==1) then print("Checking " .. w.filename) end
                    rtn2 = find_legend_count(u,w.filename,verbose)
                    if (verbose == 0) then
                        if rtn2 == 1 then return 1 end
                    end
                    if rtn2 == 1 then rtn = rtn2 end
                end
            end
    end
    if err then print(err) end
    if z then z:close() end
    os.remove(tmpname)
    return rtn
end

function common(t,o,verbose)
    rtn = 0
    if string.sub(t,1,4) == "PK\003\004" then
        rtn = xls_handler(t,verbose)
    end
    return rtn 
end

function match(args)
    local t = tostring(args["http.response_body"])
    local o = args["offset"]
    return common(t,o,0)
end

function run()
  local f = io.open(arg[1])
  local t = f:read("*all")
  f:close()
  common(t,4,1)
end
